package org.simpledao.service;

import java.lang.reflect.InvocationTargetException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.sql.DataSource;

import org.apache.commons.logging.LogFactory;
import org.apache.commons.beanutils.PropertyUtils;
import org.apache.commons.logging.Log;
//import org.apache.log4j.Logger;
import org.mytool.common.db.ColumnData;
import org.mytool.common.db.DbWhere;
import org.mytool.common.db.sql.SqlGenerate;
import org.simpledao.cache.TableInfoCacheI;
import org.simpledao.util.BeanUtil;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcTemplate;

public class SimpledaoImpl implements SimpledaoI{

//	private Logger log = Logger.getLogger(SimpledaoImpl.class);
	private Log log = LogFactory.getLog(SimpledaoImpl.class);
	private String PRE_STR_LOG_SQL = "Simpledao=>sql输出：";
	private String PRE_STR_LOG_PARA = "Simpledao=>参数输出：";
	private String tableName;

	private TableInfoCacheI tableInfo;

	private List<ColumnData> columnDatas = null;

	private List<ColumnData> primKeys = new ArrayList();

	private NamedParameterJdbcTemplate namedParameterJdbcTemplate;

	private JdbcTemplate jdbcTemplate;

	public String getTableName() {
		return tableName;
	}

	public void setTableName(String tableName) {
		this.tableName = tableName;
	}

	public SimpledaoImpl(TableInfoCacheI tableInfo, String tableName,JdbcTemplate jdbcTemplate,NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
		this.tableInfo = tableInfo;
		// setTableName(tableInfo.getd);
		this.tableName = tableName;
		this.jdbcTemplate = jdbcTemplate;
		this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
		//jdbcTemplate = new JdbcTemplate(dataSource);
		//namedParameterJdbcTemplate = new NamedParameterJdbcTemplate(jdbcTemplate);
		// this.connection = tableInfo.getConnection();
		// TODO Auto-generated method stub

		try {
			columnDatas = tableInfo.getColumnDatas(tableName);
		} catch (SQLException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}


		if (columnDatas != null) {
			for (ColumnData col : columnDatas) {
				if (col.isIfPrimKey()) {
					primKeys.add(col);
				}
			}
		}else{
			log.info("init==>"+tableName+":columnDatas is null");
		}
	}

	/**
	 * 获取表中的列元素，该方法防止初始化时没有获取到列信息
	 * @return
     */
	private List<ColumnData> getColumnDatas(){

		if(columnDatas == null){
			try {
				columnDatas = tableInfo.getColumnDatas(tableName);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}

			if (columnDatas != null &&primKeys.size() <= 0) {
				for (ColumnData col : columnDatas) {
					if (col.isIfPrimKey()) {
						primKeys.add(col);
					}
				}
			}
		}
		if(columnDatas==null){
			log.error("getColumnDatas==>"+tableName+":columnDatas is null");
		}

		return columnDatas;
	}

	
	
	public NamedParameterJdbcTemplate getNamedParameterJdbcTemplate() {
		return namedParameterJdbcTemplate;
	}

	public void setNamedParameterJdbcTemplate(NamedParameterJdbcTemplate namedParameterJdbcTemplate) {
		this.namedParameterJdbcTemplate = namedParameterJdbcTemplate;
	}

	public JdbcTemplate getJdbcTemplate() {
		return jdbcTemplate;
	}

	public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {
		this.jdbcTemplate = jdbcTemplate;
	}

	public int insert(Object data) {
		Map d = bean2Map(data);

		if (d == null) {
			return 0;
		}
		String sql = SqlGenerate.getInsertSql(tableName, getColumnDatas(), d);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+d);
		return namedParameterJdbcTemplate.update(sql, d);
	}

	public int insert(Map data) {
		String sql = SqlGenerate.getInsertSql(tableName, getColumnDatas(), data);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+data);
		return namedParameterJdbcTemplate.update(sql, data);
	}
	
	
	

	public int insertSelective(Object data) {
		Map d = bean2Map(data);

		if (d == null) {
			return 0;
		}
		String sql = SqlGenerate.getInsertSelectiveSql(tableName, getColumnDatas(), d);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+d);
		return namedParameterJdbcTemplate.update(sql, d);
	}

	public int insertSelective(Map data) {
		String sql = SqlGenerate.getInsertSelectiveSql(tableName, getColumnDatas(), data);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+data);
		return namedParameterJdbcTemplate.update(sql, data);
	}
	
	
	

	public int updateByPrimaryKey(Map data) {

		String sql = SqlGenerate.getUpdateByPrimaryKeySql(tableName, getColumnDatas(), data);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+data);
		return namedParameterJdbcTemplate.update(sql, data);
	}
	public int updateByPrimaryKey(Object data) {
		Map d = bean2Map(data);

		if (d == null) {
			return 0;
		}
		String sql = SqlGenerate.getUpdateByPrimaryKeySql(tableName, getColumnDatas(), d);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+d);
		return namedParameterJdbcTemplate.update(sql, d);
	}
	
	
	
	
	

	public int updateByParameter(Map data, DbWhere where) {
		String sql = SqlGenerate.getUpdateByWhereSql(tableName, getColumnDatas(), data, where);
		Map para = where.getParamData();
		data.putAll(para);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+data);
		return namedParameterJdbcTemplate.update(sql, data);
	}
	public int updateByParameter(Object data, DbWhere where) {
		Map d = bean2Map(data);

		if (d == null) {
			return 0;
		}
		String sql = SqlGenerate.getUpdateByWhereSql(tableName, getColumnDatas(), d, where);
		Map para = where.getParamData();
		d.putAll(para);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+d);
		return namedParameterJdbcTemplate.update(sql, d);
	}
	
	
	

	public int updateByPrimaryKeySelective(Map data) {
		String sql = SqlGenerate.getUpdateByPrimaryKeySelectiveSql(tableName, getColumnDatas(), data);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+data);
		return namedParameterJdbcTemplate.update(sql, data);
	}
	public int updateByPrimaryKeySelective(Object data) {
		Map d = bean2Map(data);

		if (d == null) {
			return 0;
		}
		String sql = SqlGenerate.getUpdateByPrimaryKeySelectiveSql(tableName, getColumnDatas(), d);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+data);
		return namedParameterJdbcTemplate.update(sql, d);
	}
	
	
	

	public int updateByParameterSelective(Map data, DbWhere where) {
		String sql = SqlGenerate.getUpdateByWhereSelectiveSql(tableName, getColumnDatas(), data, where);
		Map para = where.getParamData();
		data.putAll(para);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+data);
		return namedParameterJdbcTemplate.update(sql, data);
	}
	public int updateByParameterSelective(Object data, DbWhere where) {
		Map d = bean2Map(data);

		if (d == null) {
			return 0;
		}
		String sql = SqlGenerate.getUpdateByWhereSelectiveSql(tableName, getColumnDatas(), d, where);
		Map para = where.getParamData();
		d.putAll(para);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+d);
		return namedParameterJdbcTemplate.update(sql, d);
	}
	
	
	
	

	public int deleteByPrimaryKey(String id) {
		String prikey = null;
		if (primKeys != null && primKeys.size() > 0) {
			prikey = primKeys.get(0).getColumnName();
		}
		String sql = SqlGenerate.getDeleteByPrimaryKeySql(tableName, prikey, id);
		Map map = new HashMap();
		map.put("id", id);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+map);
		return namedParameterJdbcTemplate.update(sql, map);
	}

	public int deleteByPrimaryKeys(String... ids) {
		if (ids == null || ids.length == 0) {
			return 0;
		}
		for (String id : ids) {
			deleteByPrimaryKey(id);
		}
		return 0;
	}

	public int deleteByParameter(DbWhere where) {
		String sql = SqlGenerate.getDeleteSqlByWhere(tableName, where);
		Map paramMap = where.getParamData();
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+paramMap);
		return namedParameterJdbcTemplate.update(sql, paramMap);
	}

	public String blank2null(Object obj) {
		if (obj == null || obj.equals("")) {
			return null;
		} else {
			return obj.toString();
		}
	}

	@Override
	public Map<String, Object> selectByPrimaryKey(String id) {
		// TODO Auto-generated method stub
		String prikey = null;
		if (primKeys != null && primKeys.size() > 0) {
			prikey = primKeys.get(0).getColumnName();
		}
		String sql = SqlGenerate.getSelectSqlByPrimaryKey(tableName, prikey, id);
		log.debug(PRE_STR_LOG_SQL+sql);
		List<Map<String, Object>> list = jdbcTemplate.queryForList(sql);
		if (list != null && list.size() > 0) {
			return list.get(0);
		}
		return null;
	}

	@Override
	public List<Map<String, Object>> selectByParameter(DbWhere parameter) {
		// TODO Auto-generated method stub
		String sql = SqlGenerate.getSelectSqlByWhere(tableName, parameter);
		Map para = parameter.getParamData();
//		return jdbcTemplate.queryForList(sql);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+para);
		return namedParameterJdbcTemplate.queryForList(sql,para);
	}

	private Map bean2Map(Object bean) {
		try {
			return PropertyUtils.describe(bean);
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return null;
	}

	@Override
	public int countByParameter(DbWhere parameter) {
		// TODO Auto-generated method stub
		String sql = SqlGenerate.getCountSqlByWhere(tableName, parameter);
//		Map<String,Object> map= jdbcTemplate.queryForMap(sql);

		Map para = parameter.getParamData();
//		return jdbcTemplate.queryForList(sql);
		log.debug(PRE_STR_LOG_SQL+sql);
		log.debug(PRE_STR_LOG_PARA+para);
		Map<String,Object> map=  namedParameterJdbcTemplate.queryForMap(sql,para);

		if(map!=null){
			Long sl = map.get("sl")==null?0:(Long)map.get("sl");
			return sl.intValue();
		}
		return 0;
	}

	@Override
	public <T> T selectByPrimaryKey(String id, Class<T> cla) {
		Map map = selectByPrimaryKey(id);
		if(map==null){
			return null;
		}
		return (T)BeanUtil.toBean(cla, map);
	}

	@Override
	public <T> List<T> selectByParameter(DbWhere parameter, Class<T> cla) {
		// TODO Auto-generated method stub
		List<Map<String, Object>> list = selectByParameter(parameter);
		if(list== null ||list.size()==0){
			return null;
		}
		return BeanUtil.toBeanList(cla, list);
	}

}
